<?php

namespace app\admin\service\statistics\promotion;

use app\admin\service\statistics\completions\Completion;
use app\admin\service\statistics\filters\Filter;
use app\admin\service\statistics\groupers\Grouper;
use think\Model;

/**
 * 统计器 查询统计 抽象基类
 * Class AbstractQueryStatistician
 * @package app\admin\service\statistics\promotion
 */
abstract class AbstractQueryStatistician implements Statistician
{
    /**
     * @var Model
     */
    protected $query;

    // 筛选器
    protected array $filters = [];

    // 分组器
    protected array $groupers = [];

    // 补齐
    protected array $completions = [];

    public function setFilters(Filter ...$filters): self
    {
        foreach ($filters as $filter) {
            $this->filters[] = $filter;
        }

        return $this;
    }

    public function setGroupers(Grouper ...$groupers): self
    {

        foreach ($groupers as $grouper) {
            $this->groupers[] = $grouper;
        }

        return $this;
    }

    public function setCompletions(Completion ...$completions): self
    {
        foreach ($completions as $completion) {
            $this->completions[] = $completion;
        }

        return $this;
    }

    /**
     * 获取数据
     * @return array
     */
    public function getData(): array
    {

        $query = $this->getQuery();

        // 调用过滤器
        foreach ($this->filters as $filter) {
            $className = get_class_name($filter);
            $methodName = 'filterBy' . $className;
            if (method_exists($this, $methodName)) {
                $this->$methodName($query, $filter);
            }
        }

        // 调用分组器
        foreach ($this->groupers as $grouper) {
            $className = get_class_name($grouper);
            $methodName = 'groupBy' . $className;
            if (method_exists($this, $methodName)) {
                $this->$methodName($query, $grouper);
            }
        }

        // 执行统计查询
        if ($query) {
            $array = $query->select()->toArray();
        } else {
            $array = [];
        }


        // 调用数据补齐
        foreach ($this->completions as $completion) {
            $className = get_class_name($completion);
            $methodName = 'completionBy' . $className;
            if (method_exists($this, $methodName)) {
                $array = $this->$methodName($array, $completion);
            }
        }

        return $array;
    }

    // 固定查询条件
    abstract protected function getQuery();

}